package com.holiday.spring;

import com.holiday.spring.aop.AnnotationAppConfig;
import com.holiday.spring.config.CustomConfig;
import com.holiday.spring.domain.Video2;
import com.holiday.spring.domain.VideoOrder;
import com.holiday.spring.service.VideoService;
import com.holiday.springboot2.domain.Video;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 依赖注入
 * <!--DI 依赖注入，videoOrder这个类中属性包含 这个类 video，使用ref注入-->
 * <p>
 * spring管理类对象
 * 1、在resources路径下创建 applicationContext.xml，里面配置bean用于类的初始化
 * 2、通过自定义类，加载applicationContext.xml文件，获得到指定的bean
 * <p>
 * <p>
 * <p>
 * <p>
 * AOP使用
 * 1、自定义类，这个类是额外要做的事情，比如打印日志等；这是定义横切关注点，要做什么事情
 * 2、修改applicationContext.xml配置，增加如下标签
 * http://www.springframework.org/schema/aop
 * http://www.springframework.org/schema/aop/spring-aop-4.2.xsd"
 * xmlns:aop="http://www.springframework.org/schema/aop"
 * 3、配置applicationContext.xml AOP
 * 1、配置横切关注点
 * 2、配置AOP
 * <!--aop配置 -->
 * <aop:config>
 * <!-- 绑定 实际要执行的方法 timeHandler  -->
 * <aop:aspect id="timeAspect" ref="timeHandler">
 * <!-- 切入点：筛选出来哪些方法，切入点表达式-->
 * <aop:pointcut id="allMethodLogPointCut" expression="execution(* com.holiday.spring.service.VideoService.*(..))"/>
 * <!-- 将筛选出来的方法做什么事情 ，前置通知 -->
 * <aop:before method="printBefore" pointcut-ref="allMethodLogPointCut"/>
 * <!--将筛选出来的方法做什么事情  后置通知 -->
 * <aop:after method="printAfter" pointcut-ref="allMethodLogPointCut"/>
 * </aop:aspect>
 * </aop:config>
 * <p>
 * <p>
 * 通过注解使用Spring
 * 1、自定义类，配置开启扫描包
 *      1、通过注解方式获取bean：AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
 *      2、扫描指定的包，包括子包：context.scan("com.holiday.spring");
 *      3、里面完成初始化操作，核心方法：context.refresh();
 *      4、获取对象信息，相当于new 一个实例：VideoService videoService = (VideoService) context.getBean("videoServiceImpl");
 * 2、在各类加上注解@Component  或 @Service
 *
 *
 * 3、Spring中的xml配置与注解比较
 *      1、bean定义
 *          1、xml方式：<>bean id</>
 *          2、注解方式：@Component 通用组件 细分： @Controller (用于web层) @Service (用于service层) @Repository (用于dao仓库层)
 *      2、bean取名
 *          1、xml方式：通过id或者name
 *          2、注解方式：@Component("XXXX")
 *      3、bean注入
 *          1、xml方式：通过
 *          2、注解方式：类型注入@Autowired 名称注入@Qualifier
 *      4、bean生命周期
 *          1、xml方式：init-method、destroy-method
 *          2、注解方式：@PostConstruct初始化、@PreDestroy销毁，在对应的方法上加上注解即可
 *      5、bean作用范围，配置单例还是多例
 *          1、xml方式：scope属性
 *          2、注解方式：@scope注解，在类上加上注解即可
 *
 *事物传播行为介绍:
 *  1、@Transactional(propagation=Propagation.REQUIRED) 如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
 *  2、@Transactional(propagation=Propagation.NOT_SUPPORTED) 不为这个方法开启事务
 *  3、@Transactional(propagation=Propagation.REQUIRES_NEW) 不管是否存在事务, 都创建一个新的事务, 原来的挂起, 新的执行完毕, 继续执行老的事务
 *  4、@Transactional(propagation=Propagation.MANDATORY) 必须在一个已有的事务中执行,否则抛出异常
 *  5、@Transactional(propagation=Propagation.NEVER) 必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
 *  6、@Transactional(propagation=Propagation.SUPPORTS) 如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
 *  7、@Transactional(propagation=Propagation.NESTED) 如果当前存在事务，则创建一个事务作为当前事务的嵌套事务来运行； 如果当前没有事务，则该取值等价于Propagation.REQUIRED。
 *
 * 事务隔离级别
 *  1、@Transactional(isolation = Isolation.READ_UNCOMMITTED) 读取未提交数据(会出现脏读, 不可重复读) 基本不使用
 *  2、@Transactional(isolation = Isolation.READ_COMMITTED) 读取已提交数据(会出现不可重复读和幻读)
 *  3、@Transactional(isolation = Isolation.REPEATABLE_READ) 可重复读(会出现幻读)
 *  4、@Transactional(isolation = Isolation.SERIALIZABLE) 串行化
 *
 *
 */
public class App {

    public static void main(String[] args) throws Exception{

        annotationXml();
    }

    public static void scanSpring() {
        // 通过注解方式获取bean
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 扫描指定的包，包括子包
        context.scan("com.holiday.spring");
        // 里面完成初始化操作，核心方法
        context.refresh();
        // 获取对象信息，相当于new 一个实例
        VideoService videoService = (VideoService) context.getBean("videoServiceImpl");

        videoService.findById(1);

    }
    public  static  void xmlSpring(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        VideoService video = (VideoService) applicationContext.getBean("videoService");
    }

    public  static  void springXml(){
        // 通过注解方式获取bean
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 扫描指定的包，包括子包
        context.scan("com.holiday.spring");
        // 里面完成初始化操作，核心方法
        context.refresh();
        CustomConfig customConfig = (CustomConfig)context.getBean("customConfig");
        String host = customConfig.getHost();
        System.out.println(host);
    }
    public static void annotationXml(){
        // 通过注解方式获取bean
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnnotationAppConfig.class);
        VideoService video = (VideoService) context.getBean("videoService");
        video.findById(1);
    }


}
